{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- https://course.rs/advance/circle-self-ref/intro.html"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# * Weak 与循环引用\n",
    "\n",
    "- https://course.rs/advance/circle-self-ref/circle-reference.html\n",
    "\n",
    "TL;DR：\n",
    "\n",
    "- **循环引用成因**：`Rc<T>` + `RefCell<T>` 互相持有强引用时，引用计数永远 >0，内存无法回收，甚至可能触发无限递归打印导致栈溢出。\n",
    "- **`Weak<T>` 的作用**：弱引用不拥有所有权、不增加引用计数，可通过 `upgrade()`（返回 `Option<Rc<T>>`）临时获取强引用；资源被释放时返回 `None`。\n",
    "- **使用策略**：父节点/拥有者用 `Rc<T>` 指向子节点，子节点反向引用父节点时改用 `Weak<T>`，避免形成强引用环。\n",
    "- **示例场景**：主人-工具关系、树节点父子关系等都可通过 `Rc`（正向）+ `Weak`（反向）实现安全的双向关联。\n",
    "- **替代方案**：确实需要可变共享又无法避免环时，可考虑 `unsafe` 裸指针实现（性能高但需自行保证安全）。\n",
    "- **结论**：理解 `Weak` 的“非拥有”语义是拆解 `Rc` 循环引用的关键，实际开发中需谨慎设计引用拓扑，以免隐性内存泄漏。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Rust 的安全性是众所周知的，但是不代表它不会内存泄漏。一个典型的例子就是同时使用 `Rc<T>` 和 `RefCell<T>` 创建循环引用，最终这些引用的计数都无法被归零，因此 `Rc<T>` 拥有的值也不会被释放清理。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## * [何为循环引用](https://course.rs/advance/circle-self-ref/circle-reference.html#何为循环引用)\n",
    "\n",
    "关于内存泄漏，如果你没有充足的 Rust 经验，可能都无法造出一份代码来再现它："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "use crate::List::{Cons, Nil};\n",
    "use std::cell::RefCell;\n",
    "use std::rc::Rc;\n",
    "\n",
    "#[derive(Debug)]\n",
    "enum List {\n",
    "    Cons(i32, RefCell<Rc<List>>),\n",
    "    Nil,\n",
    "}\n",
    "\n",
    "impl List {\n",
    "    fn tail(&self) -> Option<&RefCell<Rc<List>>> {\n",
    "        match self {\n",
    "            Cons(_, item) => Some(item),\n",
    "            Nil => None,\n",
    "        }\n",
    "    }\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这里我们创建一个有些复杂的枚举类型 `List`，这个类型很有意思，它的每个值都指向了另一个 `List`，此外，得益于 `Rc` 的使用还允许多个值指向一个 `List`：\n",
    "\n",
    "![4.5.1](./images/4.5.1.png)\n",
    "\n",
    "如上图所示，每个矩形框节点都是一个 `List` 类型，它们或者是拥有值且指向另一个 `List` 的`Cons`，或者是一个没有值的终结点 `Nil`。同时，由于 `RefCell` 的使用，每个 `List` 所指向的 `List` 还能够被修改。\n",
    "\n",
    "下面来使用一下这个复杂的 `List` 枚举："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a的初始化rc计数 = 1\n",
      "a指向的节点 = Some(RefCell { value: Nil })\n",
      "在b创建后，a的rc计数 = 2\n",
      "b的初始化rc计数 = 1\n",
      "b指向的节点 = Some(RefCell { value: Cons(5, RefCell { value: Nil }) })\n",
      "在更改a后，b的rc计数 = 2\n",
      "在更改a后，a的rc计数 = 2\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "()"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "{\n",
    "    let a = Rc::new(Cons(5, RefCell::new(Rc::new(Nil))));\n",
    "\n",
    "    println!(\"a的初始化rc计数 = {}\", Rc::strong_count(&a));\n",
    "    println!(\"a指向的节点 = {:?}\", a.tail());\n",
    "\n",
    "    // 创建`b`到`a`的引用\n",
    "    let b = Rc::new(Cons(10, RefCell::new(Rc::clone(&a))));\n",
    "\n",
    "    println!(\"在b创建后，a的rc计数 = {}\", Rc::strong_count(&a));\n",
    "    println!(\"b的初始化rc计数 = {}\", Rc::strong_count(&b));\n",
    "    println!(\"b指向的节点 = {:?}\", b.tail());\n",
    "\n",
    "    // 利用RefCell的可变性，创建了`a`到`b`的引用\n",
    "    if let Some(link) = a.tail() {\n",
    "        *link.borrow_mut() = Rc::clone(&b);\n",
    "    }\n",
    "\n",
    "    println!(\"在更改a后，b的rc计数 = {}\", Rc::strong_count(&b));\n",
    "    println!(\"在更改a后，a的rc计数 = {}\", Rc::strong_count(&a));\n",
    "\n",
    "    // 下面一行println!将导致循环引用\n",
    "    // 我们可怜的8MB大小的main线程栈空间将被它冲垮，最终造成栈溢出\n",
    "    // println!(\"a next item = {:?}\", a.tail());\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这个类型定义看着复杂，使用起来更复杂！不过排除这些因素，我们可以清晰看出：\n",
    "\n",
    "1. 在创建了 `a` 后，紧接着就使用 `a` 创建了 `b`，因此 `b` 引用了 `a`\n",
    "2. 然后我们又利用 `Rc` 克隆了 `b`，然后通过 `RefCell` 的可变性，让 `a` 引用了 `b`\n",
    "\n",
    "至此我们成功创建了循环引用`a`-> `b` -> `a` -> `b` ····\n",
    "\n",
    "在 `main` 函数结束前，`a` 和 `b` 的引用计数均是 `2`，随后 `b` 触发 `Drop`，此时引用计数会变为 `1`，并不会归 `0`，因此 `b` 所指向内存不会被释放，同理可得 `a` 指向的内存也不会被释放，最终发生了内存泄漏。\n",
    "\n",
    "下面一张图很好的展示了这种引用循环关系： \n",
    "\n",
    "<img src=\"./images/4.5.2.png\" alt=\"4.5.2\" style=\"zoom:50%;\" />\n",
    "\n",
    "现在我们还需要轻轻的推一下，让塔米诺骨牌轰然倒塌。反注释最后一行代码，试着运行下："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "// https://godbolt.org/z/bMTEPK8oo\n",
    "\n",
    "{\n",
    "    let a = Rc::new(Cons(5, RefCell::new(Rc::new(Nil))));\n",
    "\n",
    "    println!(\"a的初始化rc计数 = {}\", Rc::strong_count(&a));\n",
    "    println!(\"a指向的节点 = {:?}\", a.tail());\n",
    "\n",
    "    let b = Rc::new(Cons(10, RefCell::new(Rc::clone(&a))));\n",
    "\n",
    "    println!(\"在b创建后，a的rc计数 = {}\", Rc::strong_count(&a));\n",
    "    println!(\"b的初始化rc计数 = {}\", Rc::strong_count(&b));\n",
    "    println!(\"b指向的节点 = {:?}\", b.tail());\n",
    "\n",
    "    if let Some(link) = a.tail() {\n",
    "        *link.borrow_mut() = Rc::clone(&b);\n",
    "    }\n",
    "\n",
    "    println!(\"在更改a后，b的rc计数 = {}\", Rc::strong_count(&b));\n",
    "    println!(\"在更改a后，a的rc计数 = {}\", Rc::strong_count(&a));\n",
    "\n",
    "    println!(\"a next item = {:?}\", a.tail());\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "通过 `a.tail` 的调用，Rust 试图打印出 `a -> b -> a ···` 的所有内容，但是在不懈的努力后，`main` 线程终于不堪重负，发生了[栈溢出](https://course.rs/pitfalls/stack-overflow.html)。\n",
    "\n",
    "以上的代码可能并不会造成什么大的问题，但是在一个更加复杂的程序中，类似的问题可能会造成你的程序不断地分配内存、泄漏内存，最终程序会不幸**OOM**，当然这其中的 CPU 损耗也不可小觑。\n",
    "\n",
    "总之，创建循环引用并不简单，但是也并不是完全遇不到，当你使用 `RefCell<Rc<T>>` 或者类似的类型嵌套组合（具备内部可变性和引用计数）时，就要打起万分精神，前面可能是深渊！\n",
    "\n",
    "那么问题来了？ 如果我们确实需要实现上面的功能，该怎么办？答案是使用 `Weak`。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [Weak](https://course.rs/advance/circle-self-ref/circle-reference.html#weak)\n",
    "\n",
    "`Weak` 非常类似于 `Rc`，但是与 `Rc` 持有所有权不同，`Weak` 不持有所有权，它仅仅保存一份指向数据的弱引用：如果你想要访问数据，需要通过 `Weak` 指针的 `upgrade` 方法实现，该方法返回一个类型为 `Option<Rc<T>>` 的值。\n",
    "\n",
    "看到这个返回，相信大家就懂了：何为弱引用？就是**不保证引用关系依然存在**，如果不存在，就返回一个 `None`！\n",
    "\n",
    "因为 `Weak` 引用不计入所有权，因此它**无法阻止所引用的内存值被释放掉**，而且 `Weak` 本身不对值的存在性做任何担保，引用的值还存在就返回 `Some`，不存在就返回 `None`。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### [Weak 与 Rc 对比](https://course.rs/advance/circle-self-ref/circle-reference.html#weak-与-rc-对比)\n",
    "\n",
    "我们来将 `Weak` 与 `Rc` 进行以下简单对比：\n",
    "\n",
    "| `Weak`                                          | `Rc`                                      |\n",
    "| ----------------------------------------------- | ----------------------------------------- |\n",
    "| 不计数                                          | 引用计数                                  |\n",
    "| 不拥有所有权                                    | 拥有值的所有权                            |\n",
    "| 不阻止值被释放(drop)                            | 所有权计数归零，才能 drop                 |\n",
    "| 引用的值存在返回 `Some`，不存在返回 `None`      | 引用的值必定存在                          |\n",
    "| 通过 `upgrade` 取到 `Option<Rc<T>>`，然后再取值 | 通过 `Deref` 自动解引用，取值无需任何操作 |\n",
    "\n",
    "通过这个对比，可以非常清晰的看出 `Weak` 为何这么弱，而这种弱恰恰非常适合我们实现以下的场景：\n",
    "\n",
    "- 持有一个 `Rc` 对象的临时引用，并且不在乎引用的值是否依然存在\n",
    "- 阻止 `Rc` 导致的循环引用，因为 `Rc` 的所有权机制，会导致多个 `Rc` 都无法计数归零\n",
    "\n",
    "使用方式简单总结下：**对于父子引用关系，可以让父节点通过 `Rc` 来引用子节点，然后让子节点通过 `Weak` 来引用父节点**。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### [Weak 总结](https://course.rs/advance/circle-self-ref/circle-reference.html#weak-总结)\n",
    "\n",
    "因为 `Weak` 本身并不是很好理解，因此我们再来帮大家梳理总结下，然后再通过一个例子，来彻底掌握。\n",
    "\n",
    "`Weak` 通过 `use std::rc::Weak` 来引入，它具有以下特点:\n",
    "\n",
    "- 可访问，但没有所有权，不增加引用计数，因此不会影响被引用值的释放回收\n",
    "- 可由 `Rc<T>` 调用 `downgrade` 方法转换成 `Weak<T>`\n",
    "- `Weak<T>` 可使用 `upgrade` 方法转换成 `Option<Rc<T>>`，如果资源已经被释放，则 `Option` 的值是 `None`\n",
    "- 常用于解决循环引用的问题"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "()"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "use std::rc::Rc;\n",
    "\n",
    "{\n",
    "    // 创建Rc，持有一个值5\n",
    "    let five = Rc::new(5);\n",
    "\n",
    "    // 通过Rc，创建一个Weak指针\n",
    "    let weak_five = Rc::downgrade(&five);\n",
    "\n",
    "    // Weak引用的资源依然存在，取到值5\n",
    "    let strong_five: Option<Rc<_>> = weak_five.upgrade();\n",
    "    assert_eq!(*strong_five.unwrap(), 5);\n",
    "\n",
    "    // 手动释放资源`five`\n",
    "    drop(five);\n",
    "\n",
    "    // Weak引用的资源已不存在，因此返回None\n",
    "    let strong_five: Option<Rc<_>> = weak_five.upgrade();\n",
    "    assert_eq!(strong_five, None);\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "需要承认的是，使用 `Weak` 让 Rust 本来就堪忧的代码可读性又下降了不少，但是。。。真香，因为可以解决循环引用了。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [使用 Weak 解决循环引用](https://course.rs/advance/circle-self-ref/circle-reference.html#使用-weak-解决循环引用)\n",
    "\n",
    "理论知识已经足够，现在用两个例子来模拟下真实场景下可能会遇到的循环引用。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### [工具间的故事](https://course.rs/advance/circle-self-ref/circle-reference.html#工具间的故事)\n",
    "\n",
    "工具间里，每个工具都有其主人，且多个工具可以拥有一个主人；同时一个主人也可以拥有多个工具，在这种场景下，就很容易形成循环引用，好在我们有 `Weak`："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Gadget 1 owned by Gadget Man\n",
      "Gadget 2 owned by Gadget Man\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "()"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "use std::rc::Rc;\n",
    "use std::rc::Weak;\n",
    "use std::cell::RefCell;\n",
    "\n",
    "// 主人\n",
    "struct Owner {\n",
    "    name: String,\n",
    "    gadgets: RefCell<Vec<Weak<Gadget>>>,\n",
    "}\n",
    "\n",
    "// 工具\n",
    "struct Gadget {\n",
    "    id: i32,\n",
    "    owner: Rc<Owner>,\n",
    "}\n",
    "\n",
    "{\n",
    "    // 创建一个 Owner\n",
    "    // 需要注意，该 Owner 也拥有多个 `gadgets`\n",
    "    let gadget_owner : Rc<Owner> = Rc::new(\n",
    "        Owner {\n",
    "            name: \"Gadget Man\".to_string(),\n",
    "            gadgets: RefCell::new(Vec::new()),\n",
    "        }\n",
    "    );\n",
    "\n",
    "    // 创建工具，同时与主人进行关联：创建两个 gadget，他们分别持有 gadget_owner 的一个引用。\n",
    "    let gadget1 = Rc::new(Gadget{id: 1, owner: gadget_owner.clone()});\n",
    "    let gadget2 = Rc::new(Gadget{id: 2, owner: gadget_owner.clone()});\n",
    "\n",
    "    // 为主人更新它所拥有的工具\n",
    "    // 因为之前使用了 `Rc`，现在必须要使用 `Weak`，否则就会循环引用\n",
    "    gadget_owner.gadgets.borrow_mut().push(Rc::downgrade(&gadget1));\n",
    "    gadget_owner.gadgets.borrow_mut().push(Rc::downgrade(&gadget2));\n",
    "\n",
    "    // 遍历 gadget_owner 的 gadgets 字段\n",
    "    for gadget_opt in gadget_owner.gadgets.borrow().iter() {\n",
    "\n",
    "        // gadget_opt 是一个 Weak<Gadget> 。 因为 weak 指针不能保证他所引用的对象\n",
    "        // 仍然存在。所以我们需要显式的调用 upgrade() 来通过其返回值(Option<_>)来判\n",
    "        // 断其所指向的对象是否存在。\n",
    "        // 当然，Option 为 None 的时候这个引用原对象就不存在了。\n",
    "        let gadget = gadget_opt.upgrade().unwrap();\n",
    "        println!(\"Gadget {} owned by {}\", gadget.id, gadget.owner.name);\n",
    "    }\n",
    "\n",
    "    // 在 main 函数的最后，gadget_owner，gadget1 和 gadget2 都被销毁。\n",
    "    // 具体是，因为这几个结构体之间没有了强引用（`Rc<T>`），所以，当他们销毁的时候。\n",
    "    // 首先 gadget2 和 gadget1 被销毁。\n",
    "    // 然后因为 gadget_owner 的引用数量为 0，所以这个对象可以被销毁了。\n",
    "    // 循环引用问题也就避免了\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### [tree 数据结构](https://course.rs/advance/circle-self-ref/circle-reference.html#tree-数据结构)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "leaf strong = 1, weak = 0\n",
      "branch strong = 1, weak = 1\n",
      "leaf strong = 2, weak = 0\n",
      "leaf parent = None\n",
      "leaf strong = 1, weak = 0\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "()"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "use std::cell::RefCell;\n",
    "use std::rc::{Rc, Weak};\n",
    "\n",
    "#[derive(Debug)]\n",
    "struct Node {\n",
    "    value: i32,\n",
    "    parent: RefCell<Weak<Node>>,\n",
    "    children: RefCell<Vec<Rc<Node>>>,\n",
    "}\n",
    "\n",
    "{\n",
    "    let leaf = Rc::new(Node {\n",
    "        value: 3,\n",
    "        parent: RefCell::new(Weak::new()),\n",
    "        children: RefCell::new(vec![]),\n",
    "    });\n",
    "\n",
    "    println!(\n",
    "        \"leaf strong = {}, weak = {}\",\n",
    "        Rc::strong_count(&leaf),\n",
    "        Rc::weak_count(&leaf),\n",
    "    );\n",
    "\n",
    "    {\n",
    "        let branch = Rc::new(Node {\n",
    "            value: 5,\n",
    "            parent: RefCell::new(Weak::new()),\n",
    "            children: RefCell::new(vec![Rc::clone(&leaf)]),\n",
    "        });\n",
    "\n",
    "        *leaf.parent.borrow_mut() = Rc::downgrade(&branch);\n",
    "\n",
    "        println!(\n",
    "            \"branch strong = {}, weak = {}\",\n",
    "            Rc::strong_count(&branch),\n",
    "            Rc::weak_count(&branch),\n",
    "        );\n",
    "\n",
    "        println!(\n",
    "            \"leaf strong = {}, weak = {}\",\n",
    "            Rc::strong_count(&leaf),\n",
    "            Rc::weak_count(&leaf),\n",
    "        );\n",
    "    }\n",
    "\n",
    "    println!(\"leaf parent = {:?}\", leaf.parent.borrow().upgrade());\n",
    "    println!(\n",
    "        \"leaf strong = {}, weak = {}\",\n",
    "        Rc::strong_count(&leaf),\n",
    "        Rc::weak_count(&leaf),\n",
    "    );\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [unsafe 解决循环引用](https://course.rs/advance/circle-self-ref/circle-reference.html#unsafe-解决循环引用)\n",
    "\n",
    "除了使用 Rust 标准库提供的这些类型，你还可以使用 `unsafe` 里的裸指针来解决这些棘手的问题，但是由于我们还没有讲解 `unsafe`，因此这里就不进行展开，只附上[源码链接](https://github.com/sunface/rust-algos/blob/fbcdccf3e8178a9039329562c0de0fd01a3372fb/src/unsafe/self-ref.md)，挺长的，需要耐心 o_o\n",
    "\n",
    "虽然 `unsafe` 不安全，但是在各种库的代码中依然很常见用它来实现自引用结构，主要优点如下:\n",
    "\n",
    "- 性能高，毕竟直接用裸指针操作\n",
    "- 代码更简单更符合直觉: 对比下 `Option<Rc<RefCell<Node>>>`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [总结](https://course.rs/advance/circle-self-ref/circle-reference.html#总结)\n",
    "\n",
    "本文深入讲解了何为循环引用以及如何使用 `Weak` 来解决，同时还结合 `Rc`、`RefCell`、`Weak` 等实现了两个有实战价值的例子，让大家对智能指针的使用更加融会贯通。\n",
    "\n",
    "至此，智能指针一章即将结束（严格来说还有一个 `Mutex` 放在多线程一章讲解），而 Rust 语言本身的学习之旅也即将结束，后面我们将深入多线程、项目工程、应用实践、性能分析等特色专题，来一睹 Rust 在这些领域的风采。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# * 结构体中的自引用\n",
    "\n",
    "- https://course.rs/advance/circle-self-ref/self-referential.html\n",
    "\n",
    "TL;DR：\n",
    "\n",
    "- **问题根源**：值和指向它的引用不能同时安全存在，所有权转移与借用冲突。\n",
    "- **Option 两阶段初始化**：先建值后填引用，能用但难以返回或抽象，生命周期约束多。\n",
    "- **裸指针 + `unsafe`**：直接存储 `*const/*mut` 绕过借用检查，简单但不安全，需要小心维护。\n",
    "- **`Pin` + 裸指针**：用 `Pin` 固定内存位置避免移动，再配合裸指针实现自引用，结构更安全但仍含 `unsafe`。\n",
    "- **三方库（例：`ouroboros`）**：宏生成自引用结构，接口友好但限制多（需保证内存不移动、类型受限）。\n",
    "- **其他思路**：`Rc + RefCell` / `Arc + Mutex` 组合、拆分结构、或改写算法避免自引用。\n",
    "- **实践建议**：自引用场景少见且复杂，选择方案需权衡安全、复杂度和适用性；必要时参考专门资料（如《Learn Rust by Writing Entirely Too Many Linked Lists》）。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [平平无奇的自引用](https://course.rs/advance/circle-self-ref/self-referential.html#平平无奇的自引用)\n",
    "\n",
    "可能也有不少人第一次听说自引用结构体，那咱们先来看看它们长啥样。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "struct SelfRef<'a> {\n",
    "    value: String,\n",
    "\n",
    "    // 该引用指向上面的value\n",
    "    pointer_to_value: &'a str,\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "以上就是一个很简单的自引用结构体，看上去好像没什么，那来试着运行下："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "ename": "Error",
     "evalue": "unused variable: `v`",
     "output_type": "error",
     "traceback": [
      "\u001b[31m[unused_variables] Error:\u001b[0m unused variable: `v`",
      "   \u001b[38;5;246m╭\u001b[0m\u001b[38;5;246m─\u001b[0m\u001b[38;5;246m[\u001b[0m command_11:1:1 \u001b[38;5;246m]\u001b[0m",
      "   \u001b[38;5;246m│\u001b[0m",
      " \u001b[38;5;246m3 │\u001b[0m \u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249ml\u001b[0m\u001b[38;5;249me\u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;54mv\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m=\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mS\u001b[0m\u001b[38;5;249me\u001b[0m\u001b[38;5;249ml\u001b[0m\u001b[38;5;249mf\u001b[0m\u001b[38;5;249mR\u001b[0m\u001b[38;5;249me\u001b[0m\u001b[38;5;249mf\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m{\u001b[0m",
      " \u001b[38;5;240m  │\u001b[0m         \u001b[38;5;54m┬\u001b[0m  ",
      " \u001b[38;5;240m  │\u001b[0m         \u001b[38;5;54m╰\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m warning: unused variable: `v`",
      " \u001b[38;5;240m  │\u001b[0m         \u001b[38;5;100m│\u001b[0m  ",
      " \u001b[38;5;240m  │\u001b[0m         \u001b[38;5;100m╰\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m help: if this is intentional, prefix it with an underscore: `_v`",
      "\u001b[38;5;246m───╯\u001b[0m"
     ]
    },
    {
     "ename": "Error",
     "evalue": "borrow of moved value: `s`",
     "output_type": "error",
     "traceback": [
      "\u001b[31m[E0382] Error:\u001b[0m borrow of moved value: `s`",
      "   \u001b[38;5;246m╭\u001b[0m\u001b[38;5;246m─\u001b[0m\u001b[38;5;246m[\u001b[0m command_11:1:1 \u001b[38;5;246m]\u001b[0m",
      "   \u001b[38;5;246m│\u001b[0m",
      " \u001b[38;5;246m2 │\u001b[0m \u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249ml\u001b[0m\u001b[38;5;249me\u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;68ms\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m=\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m\"\u001b[0m\u001b[38;5;249ma\u001b[0m\u001b[38;5;249ma\u001b[0m\u001b[38;5;249ma\u001b[0m\u001b[38;5;249m\"\u001b[0m\u001b[38;5;249m.\u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249mo\u001b[0m\u001b[38;5;249m_\u001b[0m\u001b[38;5;249ms\u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249mr\u001b[0m\u001b[38;5;249mi\u001b[0m\u001b[38;5;249mn\u001b[0m\u001b[38;5;249mg\u001b[0m\u001b[38;5;249m(\u001b[0m\u001b[38;5;249m)\u001b[0m\u001b[38;5;249m;\u001b[0m",
      " \u001b[38;5;240m  │\u001b[0m         \u001b[38;5;68m┬\u001b[0m  ",
      " \u001b[38;5;240m  │\u001b[0m         \u001b[38;5;68m╰\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m move occurs because `s` has type `String`, which does not implement the `Copy` trait",
      " \u001b[38;5;240m  │\u001b[0m ",
      " \u001b[38;5;246m4 │\u001b[0m \u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mv\u001b[0m\u001b[38;5;249ma\u001b[0m\u001b[38;5;249ml\u001b[0m\u001b[38;5;249mu\u001b[0m\u001b[38;5;249me\u001b[0m\u001b[38;5;249m:\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;54ms\u001b[0m\u001b[38;5;249m,\u001b[0m",
      " \u001b[38;5;240m  │\u001b[0m                \u001b[38;5;54m┬\u001b[0m\u001b[38;5;37m│\u001b[0m ",
      " \u001b[38;5;240m  │\u001b[0m                \u001b[38;5;54m╰\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m value moved here",
      " \u001b[38;5;240m  │\u001b[0m                 \u001b[38;5;37m│\u001b[0m ",
      " \u001b[38;5;240m  │\u001b[0m                 \u001b[38;5;37m╰\u001b[0m\u001b[38;5;37m─\u001b[0m help: consider cloning the value if the performance cost is acceptable: `.clone()`",
      " \u001b[38;5;246m5 │\u001b[0m \u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mp\u001b[0m\u001b[38;5;249mo\u001b[0m\u001b[38;5;249mi\u001b[0m\u001b[38;5;249mn\u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249me\u001b[0m\u001b[38;5;249mr\u001b[0m\u001b[38;5;249m_\u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249mo\u001b[0m\u001b[38;5;249m_\u001b[0m\u001b[38;5;249mv\u001b[0m\u001b[38;5;249ma\u001b[0m\u001b[38;5;249ml\u001b[0m\u001b[38;5;249mu\u001b[0m\u001b[38;5;249me\u001b[0m\u001b[38;5;249m:\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;100m&\u001b[0m\u001b[38;5;100ms\u001b[0m",
      " \u001b[38;5;240m  │\u001b[0m                           \u001b[38;5;100m─\u001b[0m\u001b[38;5;100m┬\u001b[0m  ",
      " \u001b[38;5;240m  │\u001b[0m                            \u001b[38;5;100m╰\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m value borrowed here after move",
      " \u001b[38;5;240m  │\u001b[0m ",
      " \u001b[38;5;240m  │\u001b[0m \u001b[38;5;115mNote\u001b[0m: note: deref defined here",
      "\u001b[38;5;246m───╯\u001b[0m"
     ]
    }
   ],
   "source": [
    "{\n",
    "    let s = \"aaa\".to_string();\n",
    "    let v = SelfRef {\n",
    "        value: s,\n",
    "        pointer_to_value: &s\n",
    "    };\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "因为我们试图同时使用值和值的引用，最终所有权转移和借用一起发生了。所以，这个问题貌似并没有那么好解决，不信你可以回想下自己具有的知识，是否可以解决？"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [使用 Option](https://course.rs/advance/circle-self-ref/self-referential.html#使用-option)\n",
    "\n",
    "最简单的方式就是使用 `Option` 分两步来实现："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "WhatAboutThis { name: \"Annabelle\", nickname: Some(\"Anna\") }\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "()"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#[derive(Debug)]\n",
    "struct WhatAboutThis<'a> {\n",
    "    name: String,\n",
    "    nickname: Option<&'a str>,\n",
    "}\n",
    "\n",
    "{\n",
    "    let mut tricky = WhatAboutThis {\n",
    "        name: \"Annabelle\".to_string(),\n",
    "        nickname: None,\n",
    "    };\n",
    "    tricky.nickname = Some(&tricky.name[..4]);\n",
    "\n",
    "    println!(\"{:?}\", tricky);\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在某种程度上来说，`Option` 这个方法可以工作，但是这个方法的限制较多，例如从一个函数创建并返回它是不可能的："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "ename": "Error",
     "evalue": "cannot move out of `tricky` because it is borrowed",
     "output_type": "error",
     "traceback": [
      "\u001b[31m[E0505] Error:\u001b[0m cannot move out of `tricky` because it is borrowed",
      "   \u001b[38;5;246m╭\u001b[0m\u001b[38;5;246m─\u001b[0m\u001b[38;5;246m[\u001b[0m command_13:1:1 \u001b[38;5;246m]\u001b[0m",
      "   \u001b[38;5;246m│\u001b[0m",
      " \u001b[38;5;246m1 │\u001b[0m \u001b[38;5;249mf\u001b[0m\u001b[38;5;249mn\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mc\u001b[0m\u001b[38;5;249mr\u001b[0m\u001b[38;5;249me\u001b[0m\u001b[38;5;249ma\u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249mo\u001b[0m\u001b[38;5;249mr\u001b[0m\u001b[38;5;249m<\u001b[0m\u001b[38;5;37m'\u001b[0m\u001b[38;5;37ma\u001b[0m\u001b[38;5;249m>\u001b[0m\u001b[38;5;249m(\u001b[0m\u001b[38;5;249m)\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m-\u001b[0m\u001b[38;5;249m>\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mW\u001b[0m\u001b[38;5;249mh\u001b[0m\u001b[38;5;249ma\u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249mA\u001b[0m\u001b[38;5;249mb\u001b[0m\u001b[38;5;249mo\u001b[0m\u001b[38;5;249mu\u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249mT\u001b[0m\u001b[38;5;249mh\u001b[0m\u001b[38;5;249mi\u001b[0m\u001b[38;5;249ms\u001b[0m\u001b[38;5;249m<\u001b[0m\u001b[38;5;249m'\u001b[0m\u001b[38;5;249ma\u001b[0m\u001b[38;5;249m>\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m{\u001b[0m",
      " \u001b[38;5;240m  │\u001b[0m            \u001b[38;5;37m─\u001b[0m\u001b[38;5;37m┬\u001b[0m  ",
      " \u001b[38;5;240m  │\u001b[0m             \u001b[38;5;37m╰\u001b[0m\u001b[38;5;37m─\u001b[0m\u001b[38;5;37m─\u001b[0m lifetime `'a` defined here",
      " \u001b[38;5;246m2 │\u001b[0m \u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249ml\u001b[0m\u001b[38;5;249me\u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;68mm\u001b[0m\u001b[38;5;68mu\u001b[0m\u001b[38;5;68mt\u001b[0m\u001b[38;5;68m \u001b[0m\u001b[38;5;68mt\u001b[0m\u001b[38;5;68mr\u001b[0m\u001b[38;5;68mi\u001b[0m\u001b[38;5;68mc\u001b[0m\u001b[38;5;68mk\u001b[0m\u001b[38;5;68my\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m=\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mW\u001b[0m\u001b[38;5;249mh\u001b[0m\u001b[38;5;249ma\u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249mA\u001b[0m\u001b[38;5;249mb\u001b[0m\u001b[38;5;249mo\u001b[0m\u001b[38;5;249mu\u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249mT\u001b[0m\u001b[38;5;249mh\u001b[0m\u001b[38;5;249mi\u001b[0m\u001b[38;5;249ms\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m{\u001b[0m",
      " \u001b[38;5;240m  │\u001b[0m         \u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m┬\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m  ",
      " \u001b[38;5;240m  │\u001b[0m              \u001b[38;5;68m╰\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m binding `tricky` declared here",
      " \u001b[38;5;240m  │\u001b[0m ",
      " \u001b[38;5;246m6 │\u001b[0m \u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249mr\u001b[0m\u001b[38;5;249mi\u001b[0m\u001b[38;5;249mc\u001b[0m\u001b[38;5;249mk\u001b[0m\u001b[38;5;249my\u001b[0m\u001b[38;5;249m.\u001b[0m\u001b[38;5;249mn\u001b[0m\u001b[38;5;249mi\u001b[0m\u001b[38;5;249mc\u001b[0m\u001b[38;5;249mk\u001b[0m\u001b[38;5;249mn\u001b[0m\u001b[38;5;249ma\u001b[0m\u001b[38;5;249mm\u001b[0m\u001b[38;5;249me\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m=\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mS\u001b[0m\u001b[38;5;249mo\u001b[0m\u001b[38;5;249mm\u001b[0m\u001b[38;5;249me\u001b[0m\u001b[38;5;249m(\u001b[0m\u001b[38;5;249m&\u001b[0m\u001b[38;5;100mt\u001b[0m\u001b[38;5;100mr\u001b[0m\u001b[38;5;100mi\u001b[0m\u001b[38;5;100mc\u001b[0m\u001b[38;5;100mk\u001b[0m\u001b[38;5;100my\u001b[0m\u001b[38;5;100m.\u001b[0m\u001b[38;5;100mn\u001b[0m\u001b[38;5;100ma\u001b[0m\u001b[38;5;100mm\u001b[0m\u001b[38;5;100me\u001b[0m\u001b[38;5;249m[\u001b[0m\u001b[38;5;249m.\u001b[0m\u001b[38;5;249m.\u001b[0m\u001b[38;5;249m4\u001b[0m\u001b[38;5;249m]\u001b[0m\u001b[38;5;249m)\u001b[0m\u001b[38;5;249m;\u001b[0m",
      " \u001b[38;5;240m  │\u001b[0m                             \u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m┬\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;66m│\u001b[0m ",
      " \u001b[38;5;240m  │\u001b[0m                                  \u001b[38;5;100m╰\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m borrow of `tricky.name` occurs here",
      " \u001b[38;5;240m  │\u001b[0m                                        \u001b[38;5;66m│\u001b[0m ",
      " \u001b[38;5;240m  │\u001b[0m                                        \u001b[38;5;66m╰\u001b[0m\u001b[38;5;66m─\u001b[0m help: consider cloning the value if the performance cost is acceptable: `.clone()`",
      " \u001b[38;5;240m  │\u001b[0m ",
      " \u001b[38;5;246m8 │\u001b[0m \u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;54mt\u001b[0m\u001b[38;5;54mr\u001b[0m\u001b[38;5;54mi\u001b[0m\u001b[38;5;54mc\u001b[0m\u001b[38;5;54mk\u001b[0m\u001b[38;5;54my\u001b[0m",
      " \u001b[38;5;240m  │\u001b[0m     \u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m┬\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m  ",
      " \u001b[38;5;240m  │\u001b[0m        \u001b[38;5;54m╰\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m move out of `tricky` occurs here",
      " \u001b[38;5;240m  │\u001b[0m        \u001b[38;5;97m│\u001b[0m    ",
      " \u001b[38;5;240m  │\u001b[0m        \u001b[38;5;97m╰\u001b[0m\u001b[38;5;97m─\u001b[0m\u001b[38;5;97m─\u001b[0m\u001b[38;5;97m─\u001b[0m\u001b[38;5;97m─\u001b[0m returning this value requires that `tricky.name` is borrowed for `'a`",
      "\u001b[38;5;246m───╯\u001b[0m"
     ]
    },
    {
     "ename": "Error",
     "evalue": "cannot return value referencing local data `tricky.name`",
     "output_type": "error",
     "traceback": [
      "\u001b[31m[E0515] Error:\u001b[0m cannot return value referencing local data `tricky.name`",
      "   \u001b[38;5;246m╭\u001b[0m\u001b[38;5;246m─\u001b[0m\u001b[38;5;246m[\u001b[0m command_13:1:1 \u001b[38;5;246m]\u001b[0m",
      "   \u001b[38;5;246m│\u001b[0m",
      " \u001b[38;5;246m6 │\u001b[0m \u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249mr\u001b[0m\u001b[38;5;249mi\u001b[0m\u001b[38;5;249mc\u001b[0m\u001b[38;5;249mk\u001b[0m\u001b[38;5;249my\u001b[0m\u001b[38;5;249m.\u001b[0m\u001b[38;5;249mn\u001b[0m\u001b[38;5;249mi\u001b[0m\u001b[38;5;249mc\u001b[0m\u001b[38;5;249mk\u001b[0m\u001b[38;5;249mn\u001b[0m\u001b[38;5;249ma\u001b[0m\u001b[38;5;249mm\u001b[0m\u001b[38;5;249me\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m=\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mS\u001b[0m\u001b[38;5;249mo\u001b[0m\u001b[38;5;249mm\u001b[0m\u001b[38;5;249me\u001b[0m\u001b[38;5;249m(\u001b[0m\u001b[38;5;249m&\u001b[0m\u001b[38;5;100mt\u001b[0m\u001b[38;5;100mr\u001b[0m\u001b[38;5;100mi\u001b[0m\u001b[38;5;100mc\u001b[0m\u001b[38;5;100mk\u001b[0m\u001b[38;5;100my\u001b[0m\u001b[38;5;100m.\u001b[0m\u001b[38;5;100mn\u001b[0m\u001b[38;5;100ma\u001b[0m\u001b[38;5;100mm\u001b[0m\u001b[38;5;100me\u001b[0m\u001b[38;5;249m[\u001b[0m\u001b[38;5;249m.\u001b[0m\u001b[38;5;249m.\u001b[0m\u001b[38;5;249m4\u001b[0m\u001b[38;5;249m]\u001b[0m\u001b[38;5;249m)\u001b[0m\u001b[38;5;249m;\u001b[0m",
      " \u001b[38;5;240m  │\u001b[0m                             \u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m┬\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m  ",
      " \u001b[38;5;240m  │\u001b[0m                                  \u001b[38;5;100m╰\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m `tricky.name` is borrowed here",
      " \u001b[38;5;240m  │\u001b[0m ",
      " \u001b[38;5;246m8 │\u001b[0m \u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;54mt\u001b[0m\u001b[38;5;54mr\u001b[0m\u001b[38;5;54mi\u001b[0m\u001b[38;5;54mc\u001b[0m\u001b[38;5;54mk\u001b[0m\u001b[38;5;54my\u001b[0m",
      " \u001b[38;5;240m  │\u001b[0m     \u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m┬\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m  ",
      " \u001b[38;5;240m  │\u001b[0m        \u001b[38;5;54m╰\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m returns a value referencing data owned by the current function",
      "\u001b[38;5;246m───╯\u001b[0m"
     ]
    }
   ],
   "source": [
    "fn creator<'a>() -> WhatAboutThis<'a> {\n",
    "    let mut tricky = WhatAboutThis {\n",
    "        name: \"Annabelle\".to_string(),\n",
    "        nickname: None,\n",
    "    };\n",
    "    tricky.nickname = Some(&tricky.name[..4]);\n",
    "\n",
    "    tricky\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "其实从函数签名就能看出来端倪，`'a` 生命周期是凭空产生的！\n",
    "\n",
    "如果是通过方法使用，你需要一个无用 `&'a self` 生命周期标识，一旦有了这个标识，代码将变得更加受限，你将很容易就获得借用错误，就连 NLL 规则都没用："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "ename": "Error",
     "evalue": "cannot borrow `tricky` as immutable because it is also borrowed as mutable",
     "output_type": "error",
     "traceback": [
      "\u001b[31m[E0502] Error:\u001b[0m cannot borrow `tricky` as immutable because it is also borrowed as mutable",
      "    \u001b[38;5;246m╭\u001b[0m\u001b[38;5;246m─\u001b[0m\u001b[38;5;246m[\u001b[0m command_15:1:1 \u001b[38;5;246m]\u001b[0m",
      "    \u001b[38;5;246m│\u001b[0m",
      " \u001b[38;5;246m18 │\u001b[0m \u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;100mt\u001b[0m\u001b[38;5;100mr\u001b[0m\u001b[38;5;100mi\u001b[0m\u001b[38;5;100mc\u001b[0m\u001b[38;5;100mk\u001b[0m\u001b[38;5;100my\u001b[0m\u001b[38;5;249m.\u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249mi\u001b[0m\u001b[38;5;249me\u001b[0m\u001b[38;5;249m_\u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249mh\u001b[0m\u001b[38;5;249me\u001b[0m\u001b[38;5;249m_\u001b[0m\u001b[38;5;249mk\u001b[0m\u001b[38;5;249mn\u001b[0m\u001b[38;5;249mo\u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249m(\u001b[0m\u001b[38;5;249m)\u001b[0m\u001b[38;5;249m;\u001b[0m",
      " \u001b[38;5;240m   │\u001b[0m     \u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m┬\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m  ",
      " \u001b[38;5;240m   │\u001b[0m        \u001b[38;5;100m╰\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m\u001b[38;5;100m─\u001b[0m mutable borrow occurs here",
      " \u001b[38;5;240m   │\u001b[0m ",
      " \u001b[38;5;246m21 │\u001b[0m \u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;249mp\u001b[0m\u001b[38;5;249mr\u001b[0m\u001b[38;5;249mi\u001b[0m\u001b[38;5;249mn\u001b[0m\u001b[38;5;249mt\u001b[0m\u001b[38;5;249ml\u001b[0m\u001b[38;5;249mn\u001b[0m\u001b[38;5;249m!\u001b[0m\u001b[38;5;249m(\u001b[0m\u001b[38;5;249m\"\u001b[0m\u001b[38;5;249m{\u001b[0m\u001b[38;5;249m:\u001b[0m\u001b[38;5;249m?\u001b[0m\u001b[38;5;249m}\u001b[0m\u001b[38;5;249m\"\u001b[0m\u001b[38;5;249m,\u001b[0m\u001b[38;5;249m \u001b[0m\u001b[38;5;54mt\u001b[0m\u001b[38;5;54mr\u001b[0m\u001b[38;5;54mi\u001b[0m\u001b[38;5;54mc\u001b[0m\u001b[38;5;54mk\u001b[0m\u001b[38;5;54my\u001b[0m\u001b[38;5;249m)\u001b[0m\u001b[38;5;249m;\u001b[0m",
      " \u001b[38;5;240m   │\u001b[0m                      \u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m┬\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m  ",
      " \u001b[38;5;240m   │\u001b[0m                         \u001b[38;5;54m╰\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m\u001b[38;5;54m─\u001b[0m immutable borrow occurs here",
      " \u001b[38;5;240m   │\u001b[0m                         \u001b[38;5;68m│\u001b[0m    ",
      " \u001b[38;5;240m   │\u001b[0m                         \u001b[38;5;68m╰\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m\u001b[38;5;68m─\u001b[0m mutable borrow later used here",
      "\u001b[38;5;246m────╯\u001b[0m"
     ]
    }
   ],
   "source": [
    "#[derive(Debug)]\n",
    "struct WhatAboutThis<'a> {\n",
    "    name: String,\n",
    "    nickname: Option<&'a str>,\n",
    "}\n",
    "\n",
    "impl<'a> WhatAboutThis<'a> {\n",
    "    fn tie_the_knot(&'a mut self) {\n",
    "       self.nickname = Some(&self.name[..4]);\n",
    "    }\n",
    "}\n",
    "\n",
    "{\n",
    "    let mut tricky = WhatAboutThis {\n",
    "        name: \"Annabelle\".to_string(),\n",
    "        nickname: None,\n",
    "    };\n",
    "    tricky.tie_the_knot();\n",
    "\n",
    "    // cannot borrow `tricky` as immutable because it is also borrowed as mutable\n",
    "    println!(\"{:?}\", tricky);\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [unsafe 实现](https://course.rs/advance/circle-self-ref/self-referential.html#unsafe-实现)\n",
    "\n",
    "既然借用规则妨碍了我们，那就一脚踢开："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hello, 0x7fff4d31fb58\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "()"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#[derive(Debug)]\n",
    "struct SelfRef {\n",
    "    value: String,\n",
    "    pointer_to_value: *const String,\n",
    "}\n",
    "\n",
    "impl SelfRef {\n",
    "    fn new(txt: &str) -> Self {\n",
    "        SelfRef {\n",
    "            value: String::from(txt),\n",
    "            pointer_to_value: std::ptr::null(),\n",
    "        }\n",
    "    }\n",
    "\n",
    "    fn init(&mut self) {\n",
    "        let self_ref: *const String = &self.value;\n",
    "        self.pointer_to_value = self_ref;\n",
    "    }\n",
    "\n",
    "    fn value(&self) -> &str {\n",
    "        &self.value\n",
    "    }\n",
    "\n",
    "    fn pointer_to_value(&self) -> &String {\n",
    "        assert!(!self.pointer_to_value.is_null(),\n",
    "            \"Test::b called without Test::init being called first\");\n",
    "        unsafe { &*(self.pointer_to_value) }\n",
    "    }\n",
    "}\n",
    "\n",
    "{\n",
    "    let mut t = SelfRef::new(\"hello\");\n",
    "    t.init();\n",
    "    // 打印值和指针地址\n",
    "    println!(\"{}, {:p}\", t.value(), t.pointer_to_value());\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在这里，我们在 `pointer_to_value` 中直接存储裸指针，而不是 Rust 的引用，因此不再受到 Rust 借用规则和生命周期的限制，而且实现起来非常清晰、简洁。但是缺点就是，通过指针获取值时需要使用 `unsafe` 代码。\n",
    "\n",
    "当然，上面的代码你还能通过裸指针来修改 `String`，但是需要将 `*const` 修改为 `*mut`："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hello, 0x7fff4d31fb30\n",
      "hello, world!, 0x7fff4d31fb30\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "()"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#[derive(Debug)]\n",
    "struct SelfRef {\n",
    "    value: String,\n",
    "    pointer_to_value: *mut String,\n",
    "}\n",
    "\n",
    "impl SelfRef {\n",
    "    fn new(txt: &str) -> Self {\n",
    "        SelfRef {\n",
    "            value: String::from(txt),\n",
    "            pointer_to_value: std::ptr::null_mut(),\n",
    "        }\n",
    "    }\n",
    "\n",
    "    fn init(&mut self) {\n",
    "        let self_ref: *mut String = &mut self.value;\n",
    "        self.pointer_to_value = self_ref;\n",
    "    }\n",
    "\n",
    "    fn value(&self) -> &str {\n",
    "        &self.value\n",
    "    }\n",
    "\n",
    "    fn pointer_to_value(&self) -> &String {\n",
    "        assert!(!self.pointer_to_value.is_null(), \"Test::b called without Test::init being called first\");\n",
    "        unsafe { &*(self.pointer_to_value) }\n",
    "    }\n",
    "}\n",
    "\n",
    "{\n",
    "    let mut t = SelfRef::new(\"hello\");\n",
    "    t.init();\n",
    "    println!(\"{}, {:p}\", t.value(), t.pointer_to_value());\n",
    "\n",
    "    t.value.push_str(\", world\");\n",
    "    unsafe {\n",
    "        (&mut *t.pointer_to_value).push_str(\"!\");\n",
    "    }\n",
    "\n",
    "    println!(\"{}, {:p}\", t.value(), t.pointer_to_value());\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [无法被移动的 Pin](https://course.rs/advance/circle-self-ref/self-referential.html#无法被移动的-pin)\n",
    "\n",
    "`Pin` 在后续章节会深入讲解，目前你只需要知道它可以固定住一个值，防止该值在内存中被移动。\n",
    "\n",
    "通过开头我们知道，自引用最麻烦的就是创建引用的同时，值的所有权会被转移，而通过 `Pin` 就可以很好的防止这一点："
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "上面的 `unsafe` 虽然简单好用，但是它不太安全，是否还有其他选择？还真的有，那就是 `Pin`。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "()"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "use std::marker::PhantomPinned;\n",
    "use std::pin::Pin;\n",
    "use std::ptr::NonNull;\n",
    "\n",
    "// 下面是一个自引用数据结构体，因为 slice 字段是一个指针，指向了 data 字段\n",
    "// 我们无法使用普通引用来实现，因为违背了 Rust 的编译规则\n",
    "// 因此，这里我们使用了一个裸指针，通过 NonNull 来确保它不会为 null\n",
    "struct Unmovable {\n",
    "    data: String,\n",
    "    slice: NonNull<String>,\n",
    "    _pin: PhantomPinned,\n",
    "}\n",
    "\n",
    "impl Unmovable {\n",
    "    // 为了确保函数返回时数据的所有权不会被转移，我们将它放在堆上，唯一的访问方式就是通过指针\n",
    "    fn new(data: String) -> Pin<Box<Self>> {\n",
    "        let res = Unmovable {\n",
    "            data,\n",
    "            // 只有在数据到位时，才创建指针，否则数据会在开始之前就被转移所有权\n",
    "            slice: NonNull::dangling(),\n",
    "            _pin: PhantomPinned,\n",
    "        };\n",
    "        let mut boxed = Box::pin(res);\n",
    "\n",
    "        let slice = NonNull::from(&boxed.data);\n",
    "        // 这里其实安全的，因为修改一个字段不会转移整个结构体的所有权\n",
    "        unsafe {\n",
    "            let mut_ref: Pin<&mut Self> = Pin::as_mut(&mut boxed);\n",
    "            Pin::get_unchecked_mut(mut_ref).slice = slice;\n",
    "        }\n",
    "        boxed\n",
    "    }\n",
    "}\n",
    "\n",
    "{\n",
    "    let unmoved = Unmovable::new(\"hello\".to_string());\n",
    "    // 只要结构体没有被转移，那指针就应该指向正确的位置，而且我们可以随意移动指针\n",
    "    let mut still_unmoved = unmoved;\n",
    "    assert_eq!(still_unmoved.slice, NonNull::from(&still_unmoved.data));\n",
    "\n",
    "    // 因为我们的类型没有实现 `Unpin` 特征，下面这段代码将无法编译\n",
    "    // let mut new_unmoved = Unmovable::new(\"world\".to_string());\n",
    "    // std::mem::swap(&mut *still_unmoved, &mut *new_unmoved);\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "上面的代码也非常清晰，虽然使用了 `unsafe`，其实更多的是无奈之举，跟之前的 `unsafe` 实现完全不可同日而语。\n",
    "\n",
    "其实 `Pin` 在这里并没有魔法，它也并不是实现自引用类型的主要原因，最关键的还是里面的裸指针的使用，而 `Pin` 起到的作用就是确保我们的值不会被移走，否则指针就会指向一个错误的地址！"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [使用 ouroboros](https://course.rs/advance/circle-self-ref/self-referential.html#使用-ouroboros)\n",
    "\n",
    "对于自引用结构体，三方库也有支持的，其中一个就是 [ouroboros](https://github.com/joshua-maros/ouroboros)，当然它也有自己的限制，我们后面会提到，先来看看该如何使用："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "use ouroboros::self_referencing;\n",
    "\n",
    "#[self_referencing]\n",
    "struct SelfRef {\n",
    "    value: String,\n",
    "\n",
    "    #[borrows(value)]\n",
    "    pointer_to_value: &'this str,\n",
    "}\n",
    "\n",
    "fn main(){\n",
    "    let v = SelfRefBuilder {\n",
    "        value: \"aaa\".to_string(),\n",
    "        pointer_to_value_builder: |value: &String| value,\n",
    "    }.build();\n",
    "\n",
    "    // 借用value值\n",
    "    let s = v.borrow_value();\n",
    "    // 借用指针\n",
    "    let p = v.borrow_pointer_to_value();\n",
    "    // value值和指针指向的值相等\n",
    "    assert_eq!(s, *p);\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "可以看到，`ouroboros` 使用起来并不复杂，就是需要你去按照它的方式创建结构体和引用类型：`SelfRef` 变成 `SelfRefBuilder`，引用字段从 `pointer_to_value` 变成 `pointer_to_value_builder`，并且连类型都变了。\n",
    "\n",
    "在使用时，通过 `borrow_value` 来借用 `value` 的值，通过 `borrow_pointer_to_value` 来借用 `pointer_to_value` 这个指针。\n",
    "\n",
    "看上去很美好对吧？但是你可以尝试着去修改 `String` 字符串的值试试，`ouroboros` 限制还是较多的，但是对于基本类型依然是支持的不错，以下例子来源于官方："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "use ouroboros::self_referencing;\n",
    "\n",
    "#[self_referencing]\n",
    "struct MyStruct {\n",
    "    int_data: i32,\n",
    "    float_data: f32,\n",
    "    #[borrows(int_data)]\n",
    "    int_reference: &'this i32,\n",
    "    #[borrows(mut float_data)]\n",
    "    float_reference: &'this mut f32,\n",
    "}\n",
    "\n",
    "fn main() {\n",
    "    let mut my_value = MyStructBuilder {\n",
    "        int_data: 42,\n",
    "        float_data: 3.14,\n",
    "        int_reference_builder: |int_data: &i32| int_data,\n",
    "        float_reference_builder: |float_data: &mut f32| float_data,\n",
    "    }.build();\n",
    "\n",
    "    // Prints 42\n",
    "    println!(\"{:?}\", my_value.borrow_int_data());\n",
    "    // Prints 3.14\n",
    "    println!(\"{:?}\", my_value.borrow_float_reference());\n",
    "    // Sets the value of float_data to 84.0\n",
    "    my_value.with_mut(|fields| {\n",
    "        **fields.float_reference = (**fields.int_reference as f32) * 2.0;\n",
    "    });\n",
    "\n",
    "    // We can hold on to this reference...\n",
    "    let int_ref = *my_value.borrow_int_reference();\n",
    "    println!(\"{:?}\", *int_ref);\n",
    "    // As long as the struct is still alive.\n",
    "    drop(my_value);\n",
    "    // This will cause an error!\n",
    "    // println!(\"{:?}\", *int_ref);\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "总之，使用这个库前，强烈建议看一些官方的例子中支持什么样的类型和 API，如果能满足的你的需求，就果断使用它，如果不能满足，就继续往下看。\n",
    "\n",
    "只能说，它确实帮助我们解决了问题，但是一个是破坏了原有的结构，另外就是并不是所有数据类型都支持：它需要目标值的内存地址不会改变，因此 `Vec` 动态数组就不适合，因为当内存空间不够时，Rust 会重新分配一块空间来存放该数组，这会导致内存地址的改变。\n",
    "\n",
    "类似的库还有：\n",
    "\n",
    "- [rental](https://github.com/jpernst/rental)， 这个库其实是最有名的，但是好像不再维护了，用倒是没问题\n",
    "- [owning-ref](https://github.com/Kimundi/owning-ref-rs)，将所有者和它的引用绑定到一个封装类型\n",
    "\n",
    "这三个库，各有各的特点，也各有各的缺陷，建议大家需要时，一定要仔细调研，并且写 demo 进行测试，不可大意。\n",
    "\n",
    "> rental 虽然不怎么维护，但是可能依然是这三个里面最强大的，而且网上的用例也比较多，容易找到参考代码"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [Rc + RefCell 或 Arc + Mutex](https://course.rs/advance/circle-self-ref/self-referential.html#rc--refcell-或-arc--mutex)\n",
    "\n",
    "类似于循环引用的解决方式，自引用也可以用这种组合来解决，但是会导致代码的类型标识到处都是，大大的影响了可读性。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [终极大法](https://course.rs/advance/circle-self-ref/self-referential.html#终极大法)\n",
    "\n",
    "如果两个放在一起会报错，那就分开它们。对，终极大法就这么简单，当然思路上的简单不代表实现上的简单，最终结果就是导致代码复杂度的上升。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [学习一本书：如何实现链表](https://course.rs/advance/circle-self-ref/self-referential.html#学习一本书如何实现链表)\n",
    "\n",
    "最后，推荐一本专门讲如何实现链表的书（真是富有 Rust 特色，链表都能复杂到出书了 o_o），[Learn Rust by writing Entirely Too Many Linked Lists](https://rust-unofficial.github.io/too-many-lists/)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## [总结](https://course.rs/advance/circle-self-ref/self-referential.html#总结)\n",
    "\n",
    "上面讲了这么多方法，但是我们依然无法正确的告诉你在某个场景应该使用哪个方法，这个需要你自己的判断，因为自引用实在是过于复杂。\n",
    "\n",
    "我们能做的就是告诉你，有这些办法可以解决自引用问题，而这些办法每个都有自己适用的范围，需要你未来去深入的挖掘和发现。\n",
    "\n",
    "偷偷说一句，就算是我，遇到自引用一样挺头疼，好在这种情况真的不常见，往往是实现特定的算法和数据结构时才需要，应用代码中几乎用不到。"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Rust",
   "language": "rust",
   "name": "rust"
  },
  "language_info": {
   "codemirror_mode": "rust",
   "file_extension": ".rs",
   "mimetype": "text/rust",
   "name": "rust",
   "pygment_lexer": "rust",
   "version": ""
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
